﻿namespace BM.Tools.WebControls.MForm.Controls.Helper
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web.UI;
    using BM.Tools.WebControls.MForm.Controls.Items;
    using BM.Tools.WebControls.MForm.Generator;

    /// <summary>
    /// A class that helps with prototype data creation.
    /// Prototypes are needed for dynamic items addition on the client side.
    /// </summary>
    internal class PrototypeDataHelper
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="PrototypeDataHelper"/> class.
        /// </summary>
        /// <param name="offspring">
        /// The offspring.
        /// </param>
        public PrototypeDataHelper(Offspring offspring)
        {
            Owner = offspring;
        }

        /// <summary>
        /// Gets the owner offspring.
        /// </summary>
        public Offspring Owner
        {
            get;
            private set;
        }

        /// <summary>
        /// Gets teh id separator o  the page.
        /// </summary>
        public char IdSeparator
        {
            get
            {
                return Owner.Page.IdSeparator;
            }
        }

        /// <summary>
        /// Gets the root of the MForm tree.
        /// </summary>
        public Root Root
        {
            get
            {
                return Owner.Root;
            }
        }

        private List<string> NamesList
        {
            get
            {
                var namesList = new List<string>();
                var currentOffspring = Owner;
                while (currentOffspring != Root)
                {
                    namesList.Insert(0, GetName(currentOffspring));
                    currentOffspring = currentOffspring.ParentBasis;
                }

                return namesList;
            }
        }

        private string NamesListKey
        {
            get
            {
                return String.Join("/", NamesList.ToArray());
            }
        }

        private bool IsFirst
        {
            get
            {
                if (Root == Owner)
                {
                    return true;
                }

                return Root.SelectSingle(NamesListKey).Basis == Owner;
            }
        }

        /// <summary>
        /// Gets a ScriptComponentDescriptor of a prototype associated with this offspring.
        /// </summary>
        /// <param name="events">
        /// The client side events.
        /// </param>
        /// <returns>
        /// The prototype descriptor.
        /// </returns>
        public ScriptComponentDescriptor GetPrototypeDescriptor(IDictionary<string, string> events)
        {
            if (Root != null && IsFirst)
            {
                return CreatePrototypeDescriptor(events);
            }

            return null;
        }

        internal void CreatePrototypeData()
        {
            if (Owner.ShouldRenderPrototype)
            {
                Owner.AddPrototypeItem();
            }
        }

        private string GetName(Offspring currentOffspring)
        {
            var leaf = currentOffspring as Leaf;
            if (leaf != null && leaf.LeafType == LeafType.Attribute)
            {
                return "@" + currentOffspring.Name;
            }

            return currentOffspring.Name;
        }

        private ScriptComponentDescriptor CreatePrototypeDescriptor(IDictionary<string, string> events)
        {
            var descriptor = new ScriptComponentDescriptor("MBasis");
            var rootId = Owner.Root.ClientID;
            if (Owner != Owner.Root)
            {
                if (Owner.ParentBasis != Owner.Root)
                {
                    descriptor.AddProperty("parentId", Owner.ParentBasis.ClientID.Substring(rootId.Length + 3));
                }

                descriptor.AddProperty("lastParts", GetControlsIds(Owner).Reverse().ToArray());
            }
                        
            descriptor.AddProperty("rootId", rootId);
            descriptor.AddProperty("qualifiedName", Owner.Name);
            if (Owner.MinOccurs != 1)
            {
                descriptor.AddProperty("minOccurs", Owner.MinOccurs);
            }

            if (Owner.MinRenderedOccurs != Owner.MinOccurs)
            {
                descriptor.AddProperty("minRenderedOccurs", Owner.MinRenderedOccurs);
            }

            if (Owner.MaxOccurs != 1)
            {
                descriptor.AddProperty("maxOccurs", Owner.MaxOccurs);
            }

            if (Owner.Mode == FormBuilderMode.View)
            {
                descriptor.AddProperty("mode", FormBuilderMode.View.ToString());
            }

            var leaf = Owner as Leaf;
            if (leaf != null)
            {                
                descriptor.AddProperty("dataType", leaf.DataType);    
            }
            
            foreach (var eventKeyValue in events)
            {
                descriptor.AddEvent(eventKeyValue.Key, eventKeyValue.Value);
            }

            return descriptor;
        }

        private IEnumerable<string> GetControlsIds(Offspring offspring)
        {
            Control control = offspring;
            while (!(control is OffspringItem))
            {
                yield return GetId(control);
                control = control.NamingContainer;
            }
        }

        private string GetId(Control control)
        {
            var id = control.ClientID;
            return control.ID;
        }
    }
}
